package com.example.hbutliving.service;

import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.imageaudit.model.v20191230.ScanImageRequest;
import com.aliyuncs.imageaudit.model.v20191230.ScanImageRequest.Task;
import com.aliyuncs.imageaudit.model.v20191230.ScanImageResponse;
import com.aliyuncs.imageaudit.model.v20191230.ScanImageResponse.Data.Result.SubResult;
import com.aliyuncs.profile.DefaultProfile;
import com.example.hbutliving.config.OfficialMessageType;
import com.example.hbutliving.config.WeiXinConfig;
import com.example.hbutliving.config.qiniu.QiNiuConfig;
import com.example.hbutliving.domain.receive.weixin.AccessToken;
import com.example.hbutliving.domain.receive.weixin.ContentCheckResponse;
import com.example.hbutliving.domain.send.DingMessage;
import com.example.hbutliving.exception.WeiXinException;
import com.example.hbutliving.mapper.ActivityDao;
import com.example.hbutliving.mapper.CommentDao;
import com.example.hbutliving.service.dingtalk.SendDingMessageService;
import com.example.hbutliving.util.LogUtil;
import com.example.hbutliving.util.UserUtil;
import com.google.gson.Gson;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.Header;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpHead;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

/**
 * 内容审核服务
 */
@Service
@Slf4j
public class ContentCheckService {

  @Autowired
  private Gson gson;

  @Autowired
  private RestTemplate restTemplate;

  @Autowired
  private OfficialMessageService officialMessageService;

  @Autowired
  private ActivityDao activityDao;

  @Autowired
  private CommentDao commentDao;

  private static IAcsClient client = null;

  private static volatile String TOKEN;

  private static volatile long TOKEN_EXPIRE_TIME;

  private static final String TOKEN_URL="https://api.weixin.qq.com/cgi-bin/token?grant_type={grant_type}&appid={appid}&secret={secret}";

  private static final String TEXT_URL="https://api.weixin.qq.com/wxa/msg_sec_check?access_token=";


  static {
    DefaultProfile profile = DefaultProfile.getProfile(
        "cn-shanghai",             //默认
        "LTAI4G8cPfqJhf2Pu8u7SNjw",         //您的AccessKeyID
        "a2mzvA3Tk8kcqYJU6ZGIf8kIQE3USU");    //您的AccessKeySecret

    client = new DefaultAcsClient(profile);
  }

  public String getToken() throws WeiXinException {
    if(TOKEN==null||TOKEN_EXPIRE_TIME<System.currentTimeMillis()){
      synchronized (ContentCheckService.class){
        if(TOKEN==null||TOKEN_EXPIRE_TIME<System.currentTimeMillis()){
          log.info("token 已过期,重新获取");
          Map<String,String> data=new HashMap<>(8);
          data.put("grant_type","client_credential");
          data.put("appid", WeiXinConfig.APP_ID);
          data.put("secret",WeiXinConfig.SECRET);
          ResponseEntity<AccessToken> entity = restTemplate.getForEntity(TOKEN_URL, AccessToken.class, data);
          log.info("token response:"+entity.getBody());
          if(entity.getBody()==null){
            throw new WeiXinException();
          }
          ContentCheckService.TOKEN=entity.getBody().getAccess_token();
          ContentCheckService.TOKEN_EXPIRE_TIME=System.currentTimeMillis()+7000*1000;
          return entity.getBody().getAccess_token();
        }else {
          return TOKEN;
        }
      }
    }else {
      return TOKEN;
    }
  }

  /**
   * 获取微信审核结果
   * @param content
   * @param openId
   * @return
   * @throws WeiXinException
   * @throws IOException
   */
  private ContentCheckResponse getCheckResult(String content,String openId) throws WeiXinException, IOException {
    CloseableHttpClient httpClient = HttpClientBuilder.create().build();
    HttpPost httpPost = new HttpPost(TEXT_URL+getToken());
    httpPost.setHeader("Content-Type", "application/json;charset=UTF-8");
    JSONObject jsonObject = new JSONObject();
    jsonObject.put("content",content);
    jsonObject.put("version","2");
    jsonObject.put("openid",openId);
    jsonObject.put("scene","3");
    httpPost.setEntity(new StringEntity(jsonObject.toString(),StandardCharsets.UTF_8));
    CloseableHttpResponse response = httpClient.execute(httpPost);
    ContentCheckResponse contentCheckResponse = gson.fromJson(
        EntityUtils.toString(response.getEntity()), ContentCheckResponse.class);
    log.info("contentCheckResponse:"+contentCheckResponse);
    return contentCheckResponse;
  }

  /**
   * 获取阿里云审核结果
   */
  private  boolean getCheckResult(String url) throws ClientException {
    ScanImageRequest req = new ScanImageRequest();
    List<String> scenes = new ArrayList<String>();
    scenes.add("porn");
    scenes.add("terrorism");
    req.setScenes(scenes);
    List<Task> tasks = new ArrayList<Task>();
    com.aliyuncs.imageaudit.model.v20191230.ScanImageRequest.Task task = new Task();
    task.setDataId(UUID.randomUUID().toString());
    task.setImageURL(url);
    tasks.add(task);
    req.setTasks(tasks);
    ScanImageResponse resp = client.getAcsResponse(req);
    List<SubResult> subResults = resp.getData().getResults().get(0).getSubResults();
    for (SubResult subResult : subResults) {
      if(!"pass".equals(subResult.getSuggestion())){
        return false;
      }
    }
    return true;
  }


  /**
   *  异步动态文字内容审核
   * @param content 文字内容
   * @throws WeiXinException
   * @throws IOException
   */
  @Async("checkContent")
  public void checkActivityText(String content,int activityId,int publisherId,String openId)
      throws WeiXinException, IOException {
    ContentCheckResponse contentCheckResponse = getCheckResult(content, openId);
    //审核不通过
    if(!"pass".equals(contentCheckResponse.getResult().getSuggest())){
      //删除动态
      activityDao.delete(activityId);
      //给发布者发布官方消息
      officialMessageService.sendOfficialMessage("您的动态含有违规内容,已被管理员删除",null,publisherId, OfficialMessageType.PUNISH);
      SendDingMessageService.sendContentAuditMessage(new DingMessage(publisherId+"号用户发布的"+activityId+"号动态文字内容审核未通过"));
    }
  }

  /**
   * 异步审核动态图片
   * @param picNames 图片名数组
   * @throws ClientException
   */
  @Async("checkContent")
  public void checkActivityPic(String [] picNames,int activityId,int publisherId) throws ClientException {
    for (String picName : picNames) {
      boolean isPass = getCheckResult(QiNiuConfig.URL+picName);
      if(!isPass){
        //删除动态
        activityDao.delete(activityId);
        //给发布者发布官方消息
        officialMessageService.sendOfficialMessage("您的动态含有违规内容,已被管理员删除",null,publisherId, OfficialMessageType.PUNISH);
        SendDingMessageService.sendContentAuditMessage(new DingMessage(publisherId+"号用户发布的"+activityId+"号动态图片内容审核未通过"));
        return;
      }
    }
  }

  /**
   * 审核评论
   * @param content 评论内容
   * @param commentId 评论id
   * @param publisherId 发布者id
   * @param openId 发布者openid
   * @throws WeiXinException
   * @throws IOException
   */
  @Async("checkContent")
  public void checkCommentText(String content,int commentId,int publisherId,String openId)
      throws WeiXinException, IOException {
    ContentCheckResponse contentCheckResponse = getCheckResult(content, openId);
    //审核不通过
    if(!"pass".equals(contentCheckResponse.getResult().getSuggest())){
      //删除评论
      commentDao.deleteComment(commentId);
      //给发布者发布官方消息
      officialMessageService.sendOfficialMessage("您的评论含有违规内容,已被管理员删除",null,publisherId, OfficialMessageType.PUNISH);
      SendDingMessageService.sendContentAuditMessage(new DingMessage(publisherId+"号用户发布的"+commentId+"号评论内容审核未通过"));
    }
  }

  /**
   * 审核评论回复
   * @param content 评论回复内容
   * @param commentResponseId 评论回复id
   * @param publisherId 发布者id
   * @param openId 发布者openid
   * @throws WeiXinException
   * @throws IOException
   */
  @Async("checkContent")
  public void  checkCommentResponse(String content,int commentResponseId,int publisherId,String openId)
      throws WeiXinException, IOException {
    ContentCheckResponse contentCheckResponse = getCheckResult(content, openId);
    //审核不通过
    if(!"pass".equals(contentCheckResponse.getResult().getSuggest())){
      //删除评论
      commentDao.deleteCommentResponse(commentResponseId);
      //给发布者发布官方消息
      officialMessageService.sendOfficialMessage("您的评论含有违规内容,已被管理员删除",null,publisherId, OfficialMessageType.PUNISH);
      SendDingMessageService.sendContentAuditMessage(new DingMessage(publisherId+"号用户发布的"+commentResponseId+"号评论的回复内容审核未通过"));
    }
  }


}
